package com.zwf.utils;

import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.ghost4j.document.PDFDocument;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

@Component
public class FileContentExtractor {
    @Value("${uploadPath}")
    private String tessDataPath;

    private Tesseract tesseract;

    public String extractContent(Path filePath) throws IOException {
        String fileName = filePath.getFileName().toString();
        String extension = getFileExtension(fileName);

        switch (extension.toLowerCase()) {
            case "txt":
                return extractTxt(filePath);
            case "pdf":
                return extractPdf(filePath);
            case "docx":
            case "doc":
                return extractWord(filePath);
            case "xlsx":
            case "xls":
                return extractExcel(filePath);
            case "jpg":
            case "jpeg":
            case "png":
                return extractImage(filePath);
            default:
                return "";
        }
    }

    private String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf(".");
        return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1);
    }

    private String extractTxt(Path filePath) throws IOException {
        return Files.readString(filePath);
    }

    private String extractPdf(Path filePath) throws IOException {
        try (PDDocument document = PDDocument.load(filePath.toFile())) {
            PDFTextStripper stripper = new PDFTextStripper();
            return stripper.getText(document);
        }
    }

    private String extractWord(Path filePath) throws IOException {
        try (FileInputStream fis = new FileInputStream(filePath.toFile())) {
            XWPFDocument document = new XWPFDocument(fis);
            XWPFWordExtractor extractor = new XWPFWordExtractor(document);
            return extractor.getText();
        }
    }

    private String extractExcel(Path path) throws IOException {
        StringBuilder sb = new StringBuilder();
        try (FileOutputStream fis = new FileOutputStream(path.toFile());
             XSSFWorkbook workbook = new XSSFWorkbook(fis.toString())) {
            for(Sheet sheet : workbook) {
                for (Row row : sheet) {
                    for (Cell cell : row) {
                        switch (cell.getCellType()) {
                            case STRING:
                                sb.append(cell.getStringCellValue()).append(" ");
                                break;
                            case NUMERIC:
                                sb.append(cell.getNumericCellValue()).append(" ");
                                break;
                            case BOOLEAN:
                                sb.append(cell.getBooleanCellValue()).append(" ");
                                break;
                            case FORMULA:
                                sb.append(cell.getCellFormula()).append(" ");
                                break;
                            default:
                                sb.append(" ");
                                break;
                        }
                    }
                }
            }
        }
        return sb.toString();
    }

    private String extractImage(Path filePath) throws IOException {
        if (tesseract == null) {
            initTesseract();
        }
        try {
            return tesseract.doOCR(filePath.toFile());
        } catch (TesseractException e) {
            return "";
        }
    }

    private synchronized void initTesseract() {
        if (tesseract == null) {
            tesseract = new Tesseract();
            tesseract.setDatapath(tessDataPath);
            tesseract.setLanguage("chi_sim");
        }
    }
}
